﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.XSchEmA.Aspect;
using Pixysoft.Framework.XSchEmA.Hinter;
using System.Windows.Forms;
using Pixysoft.Framework.XSchEmA.Entity;

namespace Pixysoft.Framework.XSchEmA.Verifier
{
    partial class ColumnVerifier
    {
        /// <summary>
        /// 建立外键
        /// 返回:True,False,DropUnique,
        /// </summary>
        /// <param name="columnNames"></param>
        /// <param name="database"></param>
        /// <param name="table"></param>
        /// <returns></returns>
        public bool VerifyCreatePrimaryKey(List<ColumnSchema> columns, DatabaseSchema database, TableSchema table)
        {
            if (columns == null || columns.Count == 0)
                return false;

            PrimaryKeySchema pk = database.GetPrimaryKey(table);


            //之前存在了外键，无法再添加

            if (pk != null)
            {
                msg = "存在了外键，无法再添加";
                return false;
            }


            //查看约束情况，不需要考虑外键

            UniqueSchema unique = database.GetUnique(columns);


            //没有影响，照常进行

            if (unique == null)
                return true;



            //存在一个唯一，所以需要删除原唯一

            if (unique != null)
                if (database.IsBeingForeignKey(unique.Columns))
                    if (MessageBox.Show("此列集合已经作为唯一约束，并被作为外键引用，是否删除唯一约束以继续？", "警告", MessageBoxButtons.OKCancel) == DialogResult.OK)
                        return true;
                    else
                        return false;
                else
                {
                    if (MessageBox.Show("此列集合已经作为唯一约束，是否删除唯一约束以继续？", "警告", MessageBoxButtons.OKCancel) == DialogResult.OK)
                        return true;
                    else
                        return false;
                }


            return true;
        }
        /// <summary>
        /// 验证添加主键
        /// 结果包括：建立主键、修改主键、删除唯一
        /// </summary>
        /// <returns></returns>
        private bool VerifyAddPrimaryKey(List<ColumnSchema> columns, DatabaseSchema database, TableSchema table)
        {
            if (columns == null || columns.Count == 0)
                return false;

            PrimaryKeySchema pk = database.GetPrimaryKey(table);


            //无法修改

            if (pk == null)
            {
                msg = "存在了外键，无法再添加";
                return false;
            }


            //建立修改后的pk情况列集合

            List<ColumnSchema> newcolumns = SchemaUtility.LightCloneList<ColumnSchema>(pk.Columns);

            foreach (ColumnSchema column in columns)
                if (!newcolumns.Contains(column))
                    newcolumns.Add(column);


            return _VerifyPrimaryKey(database, pk, newcolumns);

        }
        /// <summary>
        /// 验证移除主键
        /// </summary>
        /// <returns></returns>
        private bool VerifyRemovePrimaryKey(List<ColumnSchema> columns, DatabaseSchema database, TableSchema table)
        {
            PrimaryKeySchema pk = database.GetPrimaryKey(table);


            //没有东西可以移除

            if (pk == null)
                return false;


            //建立修改后的pk情况列集合

            List<ColumnSchema> newcolumns = SchemaUtility.LightCloneList<ColumnSchema>(pk.Columns);

            foreach (ColumnSchema column in columns)
                if (newcolumns.Contains(column))
                    newcolumns.Remove(column);

            return _VerifyPrimaryKey(database, pk, newcolumns);

        }
        /// <summary>
        /// CHECK CONSTRAINT
        /// </summary>
        /// <param name="database"></param>
        /// <param name="pk"></param>
        /// <param name="newcolumns"></param>
        /// <returns></returns>
        private bool _VerifyPrimaryKey(DatabaseSchema database, PrimaryKeySchema pk, List<ColumnSchema> newcolumns)
        {
            if (newcolumns.Count == pk.Columns.Count)
            {
                msg = "选定主键不存在，不需要删除。";

                return false;
            }

            //检查受影响的约束，注意，修改了pk后，对之后的fk不影响，完整性没有改变

            ForeignKeySchema fk = database.GetForeignKey(pk.Columns);

            List<ForeignKeySchema> fkList = database.GetBeingForeignKeys(pk.Columns);

            UniqueSchema unique = database.GetUnique(newcolumns);


            //修改前没有影响

            if (fk == null && fkList.Count == 0 && unique == null)
                return true;


            //修改前被外键约束了，所以不能修改，除非添加唯一

            if ((fk != null || fkList.Count > 0))
                if (MessageBox.Show("警告", "此列集合已经被外键引用，是否添加唯一约束以保持完整性？", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
                    return false;



            //修改与存在的唯一约束冲突，需要删除

            if (unique != null)
                if (MessageBox.Show("警告", "此列集合已经作为唯一约束，是否删除唯一约束以继续？", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
                    return false;


            return true;
        }
        /// <summary>
        /// 删除所有主键
        /// RETURN: TRUE, FALSE, CREATEUNIQUE
        /// </summary>
        /// <returns></returns>
        public bool VerifyDeletePrimaryKey(DatabaseSchema database, PrimaryKeySchema pk)
        {

            if (database.GetBeingForeignKeys(pk.Columns).Count != 0 &&
                MessageBox.Show("此主键已被外键引用，是否删除所有相关外键？", "警告", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
                return false;


            return true;
        }


        /// <summary>
        /// 验证添加、删除unique
        /// 返回True,False
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="myColumn">My column.</param>
        /// <returns></returns>
        public bool VerifyCreateUnique(DatabaseSchema database, string constraintName, TableSchema table, List<ColumnSchema> columns)
        {
            if (database.IsUnique(columns))//ALREADY EXISTED!
            {
                msg = "存在了相同唯一约束，无法再添加";
                return false;
            }

            if (database.IsPrimaryKey(columns))//IS PRIMARYKEY, CANNOT BE UNIQUE
            {
                msg = "存在了冲突主键，无法再添加";
                return false;
            }

            if (database.IsForeignKey(constraintName))
            {
                msg = "被外键引用了，无法添加";
                return false;
            }

            if (database.GetConstraint(constraintName) != null)
            {
                msg = "存在重复命名的约束，无法添加";
                return false;
            }

            return true;
        }
        /// <summary>
        /// 验证增加unique的column
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="myColumn">My column.</param>
        /// <returns></returns>
        private bool VerifyAddUnique(List<ColumnSchema> columns, DatabaseSchema database, UniqueSchema unique)
        {

            List<ColumnSchema> uniquecolumns = SchemaUtility.LightCloneList<ColumnSchema>(unique.Columns);

            foreach (ColumnSchema column in columns)
                if (!uniquecolumns.Contains(column))
                    uniquecolumns.Add(column);

            if (uniquecolumns.Count == unique.Columns.Count)//NOTHING TO ADD
                return false;

            return _VerifyUnique(uniquecolumns, database, unique);
        }
        /// <summary>
        /// 验证字段是否为Unique
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="myColumn">My column.</param>
        /// <returns></returns>
        private bool VerifyRemoveUnique(List<ColumnSchema> columns, DatabaseSchema database, UniqueSchema unique)
        {

            List<ColumnSchema> uniquecolumns = SchemaUtility.LightCloneList<ColumnSchema>(unique.Columns);

            foreach (ColumnSchema column in columns)
                if (uniquecolumns.Contains(column))
                    uniquecolumns.Remove(column);

            if (uniquecolumns.Count == unique.Columns.Count)//NOTHING TO ADD
                return false;

            return _VerifyUnique(uniquecolumns, database, unique);
        }
        /// <summary>
        /// 验证新columns对约束的影响
        /// </summary>
        /// <param name="columns"></param>
        /// <param name="database"></param>
        /// <returns></returns>
        private bool _VerifyUnique(List<ColumnSchema> columns, DatabaseSchema database, UniqueSchema unique)
        {
            if (database.IsPrimaryKey(columns))//IS PRIMARYKEY, CANNOT BE UNIQUE
                return false;

            if (database.IsUnique(columns))//ALREADY EXISTED!
                return false;

            if (database.IsBeingForeignKey(unique.Columns))//CANNOT CHANGE!
                return false;

            if (database.IsForeignKey(unique.Columns))//CANNOT CHANGE!
                return false;

            return true;
        }
        /// <summary>
        /// 验证添加、删除unique
        /// 返回True,False
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="myColumn">My column.</param>
        /// <returns></returns>
        public bool VerifyDeleteUnique(DatabaseSchema database, UniqueSchema unique)
        {
            if (database.GetBeingForeignKeys(unique.Columns).Count != 0 &&
                MessageBox.Show("此唯一约束已被外键引用，是否删除所有相关外键？", "警告", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
                return false;

            return true;
        }


        /// <summary>
        /// 验证外键字段更改
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="pTable">The p table.</param>
        /// <param name="pColumn">The p column.</param>
        /// <param name="database">The database.</param>
        /// <param name="fTable">The f table.</param>
        /// <param name="fColumn">The f column.</param>
        /// <returns></returns>
        private bool VerifyAlterForeignFColumn(List<ColumnSchema> fColumns, DatabaseSchema database, string fkName)
        {
            ForeignKeySchema fk = database.GetForeignKeyByName(fkName);
            if (fk == null)
                return false;

            if (fColumns.Count == 0)
                return false;

            return SchemaUtility.EuqalsDatetype(fk.FkColumns, fColumns);
        }
        /// <summary>
        /// 修改indexName
        /// </summary>
        /// <param name="fcolumnNames"></param>
        /// <param name="database"></param>
        /// <param name="fkName"></param>
        /// <returns></returns>
        private bool VerifyAlterForeignConstraintName(string constraintName, DatabaseSchema database, string fkName)
        {
            ForeignKeySchema fk = database.GetForeignKeyByName(fkName);
            if (fk == null)
                return false;

            IConstraintSchema cons = database.GetConstraint(constraintName);

            return SmartHinter.Instance.GetForeignConstraintList(database, fk.FkTable, fk.FkColumns).Contains(cons);
        }
    }
}
